/*
 * <h3>Title:wheel-spring-boot-web-starter系统</h3>
 * <p>Copyright (c) 2019, wnfbx@163.com. All rights reserved.</p>
 * @author wnfbx@163.com
 */
package com.wheel.autoconfigure.web.mvc;

import com.fasterxml.jackson.databind.JsonDeserializer;
import com.wheel.autoconfigure.jackson.deserializer.JacksonDeserializer4Date;
import com.wheel.autoconfigure.web.mvc.advice.GlobalControllerExceptionAdvice;
import com.wheel.autoconfigure.web.mvc.advice.ResultResponseBodyAdvice;
import com.wheel.autoconfigure.web.mvc.configvalidator.ConfigurationValidator;
import com.wheel.autoconfigure.web.mvc.filter.HiddenHttpMethodFilter;
import com.wheel.autoconfigure.web.mvc.filter.ResponseTimeFilter;
import com.wheel.autoconfigure.web.mvc.returnvaluehandler.ResultRequestResponseBodyMethodProcessor;
import com.wheel.core.utils.Log;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.boot.autoconfigure.AutoConfigureBefore;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.MessageSource;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.PropertySource;
import org.springframework.web.servlet.LocaleResolver;
import org.springframework.web.servlet.i18n.CookieLocaleResolver;
import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter;
import org.springframework.web.servlet.mvc.method.annotation.RequestResponseBodyMethodProcessor;

/**
 * <dt>Description:WebMvcAutoConfiguration</dt>
 * <dd>mvc 自动配置,在spring mvc配置之前配置</dd>
 * <dd>author: wnfbx</dd>
 * <dd>version:1.0 <i>2021/8/26 11:23</i></dd>
 *
 * @since jdk1.7+
 */
@Configuration
@PropertySource({"classpath:application-web.properties"})
@AutoConfigureBefore(org.springframework.boot.autoconfigure.web.servlet.WebMvcAutoConfiguration.class)
@EnableConfigurationProperties({WheelWebMvcProperties.class})
public class WebMvcAutoConfiguration {

    private static final Logger log = LoggerFactory.getLogger(WebMvcAutoConfiguration.class);

    /**
     * webMvcAutoConfigurationProperties: 配置文件
     */
    private WheelWebMvcProperties wheelWebMvcProperties;

    /**
     * <dt>Description:WebMvcAutoConfiguration</dt>
     * <dd>构造注入</dd>
     * <dd>author: wangnaifei@163.com</dd>
     * <dd>version:1.0 <i>2019/12/11 14:24</i></dd>
     *
     * @param wheelWebMvcProperties 配置
     * @since jdk1.7+
     */
    public WebMvcAutoConfiguration(WheelWebMvcProperties wheelWebMvcProperties) {
        this.wheelWebMvcProperties = wheelWebMvcProperties;
        Log.registered(log, "webMvcAutoConfigurationProperties:{}", wheelWebMvcProperties);
    }

    /**
     * <dt>Description:hiddenHttpMethodFilter</dt>
     * <dd>覆盖spring注册，解决流请求拿不到，requestInputStream会被系统获取一次的问题</dd>
     * <dd>author: wangnaifei@163.com</dd>
     * <dd>version:1.0 <i>2019/12/11 14:24</i></dd>
     *
     * @return com.wheel.core.mvc.filter.HiddenHttpMethodFilter
     * @since jdk1.7+
     */
    @Bean
    public HiddenHttpMethodFilter hiddenHttpMethodFilter() {
        Log.registered(log, HiddenHttpMethodFilter.class.getName());
        return new HiddenHttpMethodFilter();
    }

    /**
     * <dt>Description:globalControllerAdvice</dt>
     * <dd>注册，mvc异常通用处理</dd>
     * <dd>author: wangnaifei@163.com</dd>
     * <dd>version:1.0 <i>2019/12/11 14:24</i></dd>
     *
     * @return com.wheel.core.mvc.advice.GlobalControllerExecptionAdvice
     * @since jdk1.7+
     */
    @Bean
    public GlobalControllerExceptionAdvice globalControllerAdvice(MessageSource messageSource) {
        Log.registered(log, GlobalControllerExceptionAdvice.class.getName());
        return new GlobalControllerExceptionAdvice(messageSource, wheelWebMvcProperties);
    }

    @Bean("localeResolver")
    @ConditionalOnMissingBean
    public LocaleResolver defaultLocaleResolver() {
        CookieProperties i18nCookie = wheelWebMvcProperties.getI18nCookie();
        CookieLocaleResolver cookieLocaleResolver = new CookieLocaleResolver();
        if (i18nCookie != null) {
            cookieLocaleResolver.setCookieDomain(i18nCookie.getDomain());
            cookieLocaleResolver.setCookieMaxAge(i18nCookie.getMaxAge());
            cookieLocaleResolver.setCookieName(i18nCookie.getName());
            cookieLocaleResolver.setCookiePath(i18nCookie.getPath());
        }
        Log.registered(log, "Domain={}, Name={}, Path={}, MaxAge={}", cookieLocaleResolver.getCookieDomain(), cookieLocaleResolver.getCookieName(), cookieLocaleResolver.getCookiePath(), cookieLocaleResolver.getCookieMaxAge());
        return cookieLocaleResolver;
    }

    /**
     * <dt>Description:webMvcAutoConfigurerAdapter</dt>
     * <dd>注册 自定义mvc</dd>
     * <dd>author: wangnaifei@163.com</dd>
     * <dd>version:1.0 <i>2019/12/11 14:25</i></dd>
     *
     * @return com.wheel.autoconfigure.mvc.WebMvcAutoConfigurerAdapter
     * @since jdk1.7+
     */
    @Bean
    public WebMvcAutoConfigurerAdapter webMvcAutoConfigurerAdapter() {
        Log.registered(log, WebMvcAutoConfigurerAdapter.class.getName());
        return new WebMvcAutoConfigurerAdapter();
    }

    @Bean
    public ResultRequestResponseBodyMethodProcessor ResultRequestResponseBodyMethodProcessor(RequestMappingHandlerAdapter requestMappingHandlerAdapter) {
        return ResultRequestResponseBodyMethodProcessor.mvcConfigurationRegister(RequestResponseBodyMethodProcessor.class, new ResultRequestResponseBodyMethodProcessor(requestMappingHandlerAdapter.getMessageConverters()), requestMappingHandlerAdapter);
    }

    /**
     * <dt>Description:getResultMessageCodeMessageValidator</dt>
     * <dd>系统验证</dd>
     * <dd>author: wnfbx@163.com</dd>
     * <dd>version:1.0 <i>2019/12/25 20:08</i></dd>
     *
     * @param messageSource 消息
     * @return com.wheel.core.validator.ResultMessageCodeMessageValidator
     * @since jdk1.7+
     */
    @Bean
    public ConfigurationValidator getResultMessageCodeMessageValidator(MessageSource messageSource) throws Exception {
        return new ConfigurationValidator(messageSource);
    }

    @Bean
    public ResultResponseBodyAdvice getResultResponseBodyAdvice() {
        return new ResultResponseBodyAdvice();
    }

    @Bean
    public ResponseTimeFilter responseTimeFilter() {
        Log.registered(log, ResponseTimeFilter.class.getName());
        return new ResponseTimeFilter();
    }

    @Bean
    @ConditionalOnProperty(name = "w.spring.jackson.deserializer.date")
    public JsonDeserializer jacksonDeserializer4Date() {
        return new JacksonDeserializer4Date();
    }
}